package com.hmy.finance.job.core;

import cn.hutool.core.date.DateUtil;
import com.google.gson.Gson;
import com.hmy.finance.job.core.dto.DailyFeeGenerateRequestDto;
import com.hmy.finance.job.core.dto.dailyfee.DailyFeeBillGenerateProcessDto;
import com.hmy.finance.job.core.rdto.dailyfee.DailyFeeBillGenerateProcessRdto;
import com.hmy.finance.job.core.rdto.dailyfee.WaitHandleContractRdto;
import com.hmy.finance.service.core.IDailyFeeGenerateService;
import com.hmy.finance.service.core.IDeviceRentalRecordService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;

/**
 * 处理每日费用流水
 * 优化代码结构，增加流水记录的V2代码
 * <p>
 *
 * @author songkf
 */
@Slf4j
@Component
public class GenerateDeviceDailyFeeBillHandler {
    @Resource
    private IDeviceRentalRecordService deviceRentalRecordService;
    @Resource
    private IDailyFeeGenerateService dailyFeeGenerateService;

    @XxlJob("financial_generateDeviceDailyFeeBill")
    public void generateDeviceDailyFeeBill() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        log.info("Begin to generate device daily bill.Time :{}", DateUtil.now());
        //Get Params from xxl-job
        String params = XxlJobHelper.getJobParam();
        log.info("Params:{}", params);
        Gson gson = new Gson();
        DailyFeeGenerateRequestDto dailyFeeGenerateRequestDto = gson.fromJson(params, DailyFeeGenerateRequestDto.class);
        // if dailyFeeGenerateRequestDto#startDate isNull,will start handle with yesterday, and will stop until yesterday.
        // otherwise will start handle with dailyFeeGenerateRequestDto#startDate, and will stop until dailyFeeGenerateRequestDto#endDate or yesterday
        if (Objects.isNull(dailyFeeGenerateRequestDto.getStartDate())) {
            LocalDate handleDate = LocalDate.now().minusDays(1);
            dailyFeeGenerateRequestDto.setStartDate(handleDate);
            dailyFeeGenerateRequestDto.setEndDate(handleDate);
        } else {
            LocalDate handleEndDate = LocalDate.now().minusDays(1);
            //if dailyFeeGenerateRequestDto#getEndDate is not null and dailyFeeGenerateRequestDto#getEndDate is before handleEndDate,then set dailyFeeGenerateRequestDto#getEndDate to handleEndDate
            if (Objects.nonNull(dailyFeeGenerateRequestDto.getEndDate()) && dailyFeeGenerateRequestDto.getEndDate().isBefore(handleEndDate)) {
                handleEndDate = dailyFeeGenerateRequestDto.getEndDate();
            }
            dailyFeeGenerateRequestDto.setStartDate(dailyFeeGenerateRequestDto.getStartDate());
            dailyFeeGenerateRequestDto.setEndDate(handleEndDate);
        }
        //Select the wait Handle Contract Info List
        List<WaitHandleContractRdto> waitHandleContractIdSet = deviceRentalRecordService.getWaitHandleContractInfoList(dailyFeeGenerateRequestDto);

        for (WaitHandleContractRdto waitHandleContractRdto : waitHandleContractIdSet) {

            DailyFeeBillGenerateProcessRdto processRdto = dailyFeeGenerateService.generateDailyFeeBill(buildProcessDto(waitHandleContractRdto, dailyFeeGenerateRequestDto));
            if (processRdto.isSuccess()) {
                log.info("Generate daily fee bill success.ContractId:{},BillThroughDate:{}", processRdto.getContractId(), processRdto.getBillThroughDate());
            } else {
                log.error("Generate daily fee bill failed.ContractId:{},BillThroughDate:{}", processRdto.getContractId(), processRdto.getBillThroughDate());
            }
        }
        stopWatch.stop();
        log.info("End to generate device daily bill.Duration: {} s, Time:{}", stopWatch.getTotalTimeSeconds(), DateUtil.now());
    }

    private static DailyFeeBillGenerateProcessDto buildProcessDto(WaitHandleContractRdto waitHandleContractRdto, DailyFeeGenerateRequestDto dailyFeeGenerateRequestDto) {
        DailyFeeBillGenerateProcessDto processDto = new DailyFeeBillGenerateProcessDto();
        processDto.setContractId(waitHandleContractRdto.getContractId());
        processDto.setHandleStartDate(dailyFeeGenerateRequestDto.getStartDate());
        // if waitHandleContractRdto#endDate is null,then set loop times is dailyFeeGenerateRequestDto#endDate - dailyFeeGenerateRequestDto#startDate
        // otherwise set loop times is waitHandleContractRdto#endDate - dailyFeeGenerateRequestDto#startDate
        if (Objects.isNull(waitHandleContractRdto.getEndDate())) {
            processDto.setLoopTimes(ChronoUnit.DAYS.between(dailyFeeGenerateRequestDto.getEndDate(), dailyFeeGenerateRequestDto.getStartDate()) + 1);
        } else {
            processDto.setLoopTimes(ChronoUnit.DAYS.between(waitHandleContractRdto.getEndDate(), dailyFeeGenerateRequestDto.getStartDate()) + 1);
        }
        return processDto;
    }
}
